package com.tingyukeji.fastpay.entity;

import android.app.Activity;
import android.databinding.ViewDataBinding;
import android.os.Handler;
import android.os.Looper;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.kaopiz.kprogresshud.KProgressHUD;
import com.sc.utils.ThreadPool;
import com.tingyukeji.fastpay.MainApplication;
import com.tingyukeji.fastpay.data.HostHelper;
import com.tingyukeji.fastpay.data.net.OkHttpUtils;
import com.tingyukeji.fastpay.data.net.ReqCallBack;
import com.tingyukeji.fastpay.utils.ACache;
import com.tingyukeji.fastpay.utils.LogUtils;
import com.tingyukeji.fastpay.utils.ReflectUtils;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.LinkedHashMap;

/**
 * Created by Administrator on 2016/11/8.
 */

public abstract class BaseReqEntity extends BaseEntity {

    public static final int POST = 2;
    public static final int GET = 1;
    public static final int UPLOAD=3;

    public static final int STRAGE_DEFAULT = 1;//仅网络请求
    public static final int STRAGE_HASCACHE_ONLY = 2;//先看缓存有没有，有就用缓存不请求网络，否则请求
    public static final int STRAGE_HASCACHE_UPDATE = 3;//先看缓存有没有，有就先用缓存再请求网络更新

    public static final String[] NEED_UID_URLS = {
//            HostHelper.BANNER_URL
//            , HostHelper.PRODUCT_LIST_URL
//            , HostHelper.LIVE_LIST_URL
    };

    private ReqCompletedLisener lisener;
    private LinkedHashMap<String, Object> params;
    private int index_BaseReqEntity = 0;
    private int reqType_BaseReqEntity = GET;//1
    private int reqCache_Strage = STRAGE_DEFAULT;//1
    private int reqCache_Time = 3 * 24 * 60 * 60;//缓存3天
    private String reqCache_String;//1
    private boolean reqCallBack_UIthread = true;//默认强制ui线程返回
    private boolean reqCallBack_ShowLoaddingOnce = false;//是否显示一次
    private boolean reqCallBack_ShowLoaddingOnceFlg = false;
    private boolean reqCallBack_CacheAll = false;//true请求成功或者没有标示都要返回
    private boolean reqCallBack_CacheAfterUpdate_Run = false;//true读缓存但强制仅返回网络（正常）返回
    private boolean reqCallBack_CacheOpen = false;//是否开启缓存，策略为非default默认开启
    private transient Activity act;

    private boolean success;
    private String msg;

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public BaseReqEntity setParams(LinkedHashMap params) {
        this.params = params;
        return this;
    }

    public BaseReqEntity setActivity(Activity act) {
        this.act = act;
        return this;
    }

    public BaseReqEntity putParam(String key, String value) {
        if (this.params == null) {
            params = new LinkedHashMap();
        }
        this.params.put(key, value);
        return this;
    }

    public BaseReqEntity putParam(String key, Object value) {
        if (this.params == null) {
            params = new LinkedHashMap();
        }
        this.params.put(key, value);
        return this;
    }

    public BaseReqEntity clearParams() {
        if (this.params == null) {
            params = new LinkedHashMap();
        }
        this.params.clear();
        return this;
    }

    public BaseReqEntity setIndex(int index) {
        this.index_BaseReqEntity = index;
        return this;
    }

    public BaseReqEntity setCacheOpen(boolean open) {
        this.reqCallBack_CacheOpen = open;
        return this;
    }

    public BaseReqEntity setShowLoaddingOnce(boolean flg) {
        this.reqCallBack_ShowLoaddingOnce = flg;
        return this;
    }

    public BaseReqEntity setCacheStrage(int strage) {
        this.reqCache_Strage = strage;
        if (strage != STRAGE_DEFAULT) {
            reqCallBack_CacheOpen = true;
        }
        return this;
    }

    public BaseReqEntity setCallBackUIThread(boolean flg) {
        this.reqCallBack_UIthread = flg;
        return this;
    }

    public BaseReqEntity setCallBackCacehAll(boolean flg) {
        this.reqCallBack_CacheAll = flg;
        return this;
    }

    public BaseReqEntity setCallBackCacehAfterUpdateRun(boolean flg) {
        this.reqCallBack_CacheAfterUpdate_Run = flg;
        return this;
    }

    /**
     * 设置缓存时间
     *
     * @param time 秒
     * @return
     */
    public BaseReqEntity setCacheTime(int time) {
        this.reqCache_Time = time;
        return this;
    }

    public BaseReqEntity setReqType(int reqMethod) {
        this.reqType_BaseReqEntity = reqMethod;
        return this;
    }

    public int getIndex() {
        return this.index_BaseReqEntity;
    }

    public ReqCompletedLisener getLisener() {
        return lisener;
    }

    public BaseReqEntity setLisener(ReqCompletedLisener lisener) {
        this.lisener = lisener;
        return this;
    }

    public void execute() {
        getData(this.params, null, null, null);
    }

    public void execute(KProgressHUD mKProgressHUD) {
        getData(this.params, mKProgressHUD, null, null);
    }

    public void execute(ViewDataBinding viewDataBinding, String layoutVarName) {
        getData(this.params, null, viewDataBinding, layoutVarName);
    }

    public void execute(KProgressHUD mKProgressHUD, ViewDataBinding viewDataBinding, String layoutVarName) {
        getData(this.params, mKProgressHUD, viewDataBinding, layoutVarName);
    }

    public abstract TypeHodler __getClsType();

    public String getCache() {
        return ACache.get(MainApplication.App.getApplicationContext()).getAsString(getCacheKey(__getClsType().url, params));
    }

    public <T> T getCacheObject() {
        Gson gson = new Gson();
        String cache = getCache();
        if (cache != null) {
            BaseReqEntity beans = gson.fromJson(cache, __getClsType().type);
            return (T) beans;
        }
        return null;
    }

    public static <T> T getCacheObject(String url, LinkedHashMap<String, Object> params, Type type) {
        Gson gson = new Gson();
        String cache = ACache.get(MainApplication.App.getApplicationContext()).getAsString(getCacheKey(url, params));
        if (cache != null) {
            BaseReqEntity beans = gson.fromJson(cache, type);
            return (T) beans;
        }
        return null;
    }

    private void getData(final LinkedHashMap<String, Object> params, final KProgressHUD mKProgressHUD, final ViewDataBinding viewDataBinding, final String layoutVarName) {
        final Handler handler = new Handler(Looper.getMainLooper());
        final Gson gson = new Gson();
        if (mKProgressHUD != null && !mKProgressHUD.isShowing() && !reqCallBack_ShowLoaddingOnceFlg) {
            try {
                mKProgressHUD.show();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (reqCallBack_ShowLoaddingOnce) {
            reqCallBack_ShowLoaddingOnceFlg = true;
        }
        insertParams(__getClsType().url, params);
        final boolean checkNet = OkHttpUtils.getInstance().checkNet();
        ThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                if (reqCache_Strage != STRAGE_DEFAULT) {
                    reqCache_String = ACache.get(MainApplication.App.getApplicationContext()).getAsString(getCacheKey(__getClsType().url, params));
                    if (reqCache_String != null) {
                        if (checkNet && reqCache_Strage == STRAGE_HASCACHE_UPDATE && reqCallBack_CacheAfterUpdate_Run) {

                        } else {
                            if (reqCallBack_UIthread) {
                                handler.post(new Runnable() {

                                    @Override
                                    public void run() {
                                        getCallBack(handler, gson, mKProgressHUD, viewDataBinding, layoutVarName, true).onSuccess(reqCache_String);
                                    }
                                });
                            } else {
                                getCallBack(handler, gson, mKProgressHUD, viewDataBinding, layoutVarName, true).onSuccess(reqCache_String);
                            }
                        }


                        if (reqCache_Strage == STRAGE_HASCACHE_ONLY) {
                            return;
                        }
                    }
                }

                if (!checkNet) {
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            if (mKProgressHUD != null) {
                                mKProgressHUD.dismiss();
                            }
                            if (lisener == null) {
                                LogUtils.d("ReqCompletedLisener not set!!!!!!!!!!!!!!!!");
                                return;
                            }
                            if (reqCache_Strage != STRAGE_DEFAULT && reqCache_String != null) {

                            } else {
                                lisener.notifyReqCompleted(false, null, "暂无网络", false);
                            }
                        }
                    });
                    return;
                }

                if (reqType_BaseReqEntity == GET) {
                    OkHttpUtils.getInstance().get(__getClsType().url, params, getCallBack(handler, gson, mKProgressHUD, viewDataBinding, layoutVarName, false));
                } else if (reqType_BaseReqEntity == POST) {
                    OkHttpUtils.getInstance().post(__getClsType().url, params, getCallBack(handler, gson, mKProgressHUD, viewDataBinding, layoutVarName, false));
                }else if(reqType_BaseReqEntity==UPLOAD){
                    OkHttpUtils.getInstance().upLoadFile(__getClsType().url,params,getCallBack(handler, gson, mKProgressHUD, viewDataBinding, layoutVarName, false));
                }
                LogUtils.d(getUrl(" basereq == req : " + __getClsType().url, params));
            }
        });
    }

    private static String getCacheKey(String url, LinkedHashMap<String, Object> param) {

        return getFilenameForKey(getUrl(url, param));
    }

    private static String getUrl(String url, LinkedHashMap<String, Object> param) {
        if (null != param) {
            String stringBuffer = "?";
            int i = 0;
            for (String key : param.keySet()) {
                if (i > 0) stringBuffer += "&";
                stringBuffer += key;
                stringBuffer += "=";
                stringBuffer += param.get(key);
                i++;
            }
            url += stringBuffer.toString();
        }
        return url;
    }

    private static String getFilenameForKey(String key) {
        int firstHalfLength = key.length() / 2;
        String localFilename = String.valueOf(key.substring(0, firstHalfLength).hashCode());
        localFilename += String.valueOf(key.substring(firstHalfLength).hashCode());
        return localFilename;
    }

    private void insertParams(String url, LinkedHashMap<String, Object> params) {
//        String uid = AppUtils.getUID(MainApplication.App.getApplicationContext());
//        if (!"".equals(uid)&&needUID(url)) {
//            params.put("belong", uid);
//        }
    }

    private boolean needUID(String url) {
        int size = NEED_UID_URLS.length;
//        for (int i = 0; i < size; i++) {
//            if (NEED_UID_URLS[i].equals(url)) {
//                return true;
//            }
//        }
        return true;
    }

    private ReqCallBack.ReqCallBackListener getCallBack(final Handler handler, final Gson gson, final KProgressHUD mKProgressHUD, final ViewDataBinding viewDataBinding, final String layoutVarName, final boolean cacheReq) {
        return new ReqCallBack.ReqCallBackListener() {

            @Override
            public void onSuccess(final String result) {
                if (mKProgressHUD != null) {
                    mKProgressHUD.dismiss();
                }
                if (act != null && (act.isDestroyed() || act.isFinishing())) {
                    return;
                }
                if (result != null) {
                    try {
                        final Object beans = gson.fromJson(result, __getClsType().type);
                        if (beans == null) {
                            onFail("数据解析失败");
                            return;
                        }
                        if (reqCallBack_UIthread) {
                            handler.post(new Runnable() {

                                @Override
                                public void run() {
                                    runBack(beans, result);
                                }
                            });
                        } else {
                            runBack(beans, result);
                        }
                    } catch (JsonSyntaxException e) {
                        if (null != lisener) lisener.notifyReqCompleted(false, null, "", false);
                        e.printStackTrace();
                    }
                }
            }

            public void runBack(Object beans, final String result) {
                LogUtils.d(" basereq == result: " + result);
                if (reqCallBack_CacheAll || (beans instanceof BaseReqEntity && ((BaseReqEntity) beans).isSuccess())) {
                    if (lisener != null) {
//                        if (!isCacheOpen&&reqCache_Strage == STRAGE_HASCACHE_UPDATE && reqCache_String != null) {
//                            if (reqCache_Strage == STRAGE_HASCACHE_UPDATE && reqCallBack_CacheAfterUpdate_Run) {
//                                lisener.notifyReqCompleted(beans.isSuccess(), beans, null, isCacheOpen);
//                            }
//                        } else {
//                            lisener.notifyReqCompleted(beans.isSuccess(), beans, null, isCacheOpen);
//                        }
                        lisener.notifyReqCompleted((beans instanceof BaseReqEntity ? ((BaseReqEntity) beans).isSuccess() : false), beans, null, cacheReq);
                        if (!cacheReq && reqCallBack_CacheOpen) {
                            ThreadPool.execute(new Runnable() {
                                @Override
                                public void run() {
                                    if (reqCache_Time == 0) {
                                        ACache.get(MainApplication.App.getApplicationContext()).put(getCacheKey(__getClsType().url, params), result);
                                    } else {
                                        ACache.get(MainApplication.App.getApplicationContext()).put(getCacheKey(__getClsType().url, params), result, reqCache_Time);
                                    }
                                }
                            });
                        }
                    } else {
                        LogUtils.d("ReqCompletedLisener not set!!!!!!!!!!!!!!!!");
                    }
                    if (viewDataBinding != null) {
                        Method method = ReflectUtils.getMethod(viewDataBinding.getClass(), "set" + captureName(layoutVarName), beans.getClass());
                        if (method != null) {
                            try {
                                ReflectUtils.invokeMethod(method, viewDataBinding, beans);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }

                } else {
                    if (lisener != null) {
                        lisener.notifyReqCompleted((beans instanceof BaseReqEntity ? ((BaseReqEntity) beans).isSuccess() : false), beans, beans instanceof BaseReqEntity ? ((BaseReqEntity) beans).getMsg() : "", false);
                    } else {
                        LogUtils.d("ReqCompletedLisener not set!!!!!!!!!!!!!!!!");
                    }

                }

            }

            @Override
            public void onFail(final String msg) {
                LogUtils.d(" basereq == result: " + msg);
                if (act != null && (act.isDestroyed() || act.isFinishing())) {
                    return;
                }
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (mKProgressHUD != null) {
                            try {
                                mKProgressHUD.dismiss();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                        if (lisener == null) {
                            LogUtils.d("ReqCompletedLisener not set!!!!!!!!!!!!!!!!");
                            return;
                        }
                        if (cacheReq && reqCache_String != null) {

                        } else {
                            lisener.notifyReqCompleted(false, null, msg, false);
                        }

                    }
                });
            }
        };
    }

    //首字母大写
    public static String captureName(String name) {
        //     name = name.substring(0, 1).toUpperCase() + name.substring(1);
//        return  name;
        char[] cs = name.toCharArray();
        cs[0] -= 32;
        return String.valueOf(cs);

    }

    public class TypeHodler {
        public TypeHodler(String url, Type type) {
            this.url = url;
            this.type = type;
        }

        public String url;
        public Type type;
    }
}
